package top.hcode.hoj.service.admin;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.nutz.lang.Lang;
import org.nutz.lang.util.NutMap;
import org.sagacity.sqltoy.model.MapKit;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import top.hcode.hoj.common.LazyDao;
import top.hcode.hoj.dao.CollUserAnswerDao;
import top.hcode.hoj.dao.CollUserStatDao;
import top.hcode.hoj.dao.collect.ItechCollDao;
import top.hcode.hoj.dao.org.OrgDao;
import top.hcode.hoj.pojo.entity.CollUserStat;
import top.hcode.hoj.pojo.entity.coll.ItechCollection;
import top.hcode.hoj.pojo.event.CollUserStatUpdateEvent;
import top.hcode.hoj.pojo.form.coll.AdmQueryCollUserStatForm;
import top.hcode.hoj.pojo.vo.coll.CollUserStatVO;
import top.hcode.hoj.utils.PageUtil;
import top.hcode.hoj.utils.SqlUtil;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static org.nutz.lang.Strings.isNotBlank;

/**
 * @author orangej
 * @since 2025-02-10
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class AdminCollUserStatService {
    private final ItechCollDao collDao;
    private final CollUserStatDao userStatDao;
    private final CollUserAnswerDao userAnswerDao;
    private final OrgDao orgDao;
    private final LazyDao dao;

    @EventListener
    @Transactional
    public void handleCollUserStatChangeEvent(CollUserStatUpdateEvent event) {
        String collId = event.getCollId();
        String userId = event.getUserId();
        updateCollUserStat(userId, collId);
    }

    /**
     * 更新用户统计信息的所有字段
     */
    @Transactional
    public void updateCollUserStat(String userId, String collId) {
        CollUserStat userStat = userStatDao.getByUserIdAndCollId(userId, collId);
        if (userStat == null) {
            userStat = new CollUserStat();
            userStat.setUserId(userId);
            userStat.setCollId(collId);
            userStatDao.save(userStat);
        }

        dao.runSql("updateCollUserStatOne", MapKit.map("id", userStat.getId()));
    }

    /**
     * 获取用户统计信息，不存在时自动新建
     */
    @Transactional
    public CollUserStat getOrCreateCollUserStat(String userId, String collId) {
        CollUserStat userStat = userStatDao.getByUserIdAndCollId(userId, collId);
        if (userStat == null) {
            userStat = new CollUserStat();
            userStat.setUserId(userId);
            userStat.setCollId(collId);
            userStatDao.save(userStat);

            dao.runSql("updateCollUserStatOne", MapKit.map("id", userStat.getId()));
            return userStatDao.getById(userStat.getId());
        }
        return userStat;
    }

    /**
     * 更新客观题得分
     */
    public void updateObjectiveScore(String uid, String collId) {
        // 计算客观题得分
        BigDecimal score = userAnswerDao.sumChoiceQuestionScore(uid, collId);
        CollUserStat userStat = getOrCreateCollUserStat(uid, collId);
        if (score.compareTo(userStat.getObjectiveScore()) != 0) {
            userStat.setObjectiveScore(score);
            userStat.setTotalScore(score.add(userStat.getSubjectiveScore()));
            userStatDao.updateById(userStat);
        }
    }

    public IPage<CollUserStatVO> queryCollUserStatVO(AdmQueryCollUserStatForm form, List<String> schoolIdList) {
        List<String> classIdList = orgDao.queryClassIdOf(form.getClassId(), form.getGradeId(), form.getSchoolId(), schoolIdList);

        NutMap params = Lang.obj2nutmap(form);
        params.addv("classIdList", classIdList);

        return PageUtil.toMybatis(dao.selectPage(form.getCurrentPage(), form.getLimit(),
                CollUserStatVO.class, "queryCollUserStatVO", params));
    }

    public CollUserStat getCollUserStat(Long id) {
        return userStatDao.getById(id);
    }

    public CollUserStat saveCollUserStat(CollUserStat collUserStat) {
        userStatDao.saveOrUpdate(collUserStat);
        return collUserStat;
    }

    @Transactional
    public void deleteCollUserStat(Long id) {
        CollUserStat userStat = userStatDao.getById(id);
        if (userStat == null) {
            return;
        }

        userStatDao.removeById(id);
        String collId = userStat.getCollId();
        String userId = userStat.getUserId();
        userAnswerDao.removeByMap(MapKit.startOf("coll_id", collId).endOf("user_id", userId));
    }
}
